package ts;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;


public class Funciones {

	public static TablaSimbolos creaTS(String id, String clase, Tipo tipo, int dir) {
		TablaSimbolos ts = new TablaSimbolos();
		if (!tipo.getTipo().equals("errorTipo"))
			ts.anadeTS(id, clase, tipo, dir);
		return ts;
	}

	public static TablaSimbolos creaTS() {
		TablaSimbolos ts = new TablaSimbolos();
		return ts;
	}

	public static TablaSimbolos creaTS(TablaSimbolos ts, String id,
			String clase, ArrayList<Boolean> err, Tipo tipo, int dir) {
		TablaSimbolos tsNueva = new TablaSimbolos(ts);
		if (!hayError(err) && !tipo.getTipo().equals("errorTipo")) {
			if (clase.equals("tipo"))
				tsNueva.anadeTS(id, clase, tipo, 0);
			else
				tsNueva.anadeTS(id, clase, tipo, dir);
		}
		return tsNueva;
	}
	
	public static ArrayList<Boolean> creaErrores() {
		ArrayList<Boolean> errores = new ArrayList<Boolean>();
		for (int i = 0; i < 8; i++)
			errores.add(false);
		return errores;
	}

	public static boolean hayError(ArrayList<Boolean> e) {
		boolean hayErrores = false;
		for (int i = 0; i < e.size(); i++)
			hayErrores |= e.get(i);
		return hayErrores;
	}

	public static ArrayList<Boolean> unirErrores(ArrayList<Boolean> e1,
			ArrayList<Boolean> e2) {
		ArrayList<Boolean> errores = new ArrayList<Boolean>();
		for (int i = 0; i < e1.size(); i++)
			errores.add(e1.get(i) | e2.get(i));
		return errores;
	}

	public static ArrayList<Boolean> unirErrores(ArrayList<Boolean> e1,
			ArrayList<Boolean> e2, ArrayList<Boolean> e3, ArrayList<Boolean> e4) {
		return unirErrores(unirErrores(e1, e2), unirErrores(e3, e4));
	}
	
	public static ArrayList<Boolean> unirErrores(ArrayList<Boolean> e1,
			ArrayList<Boolean> e2, ArrayList<Boolean> e3, ArrayList<Boolean> e4, ArrayList<Boolean> e5) {
		return unirErrores(unirErrores(e1, e2), unirErrores(e3, e4,e5));
	}
	
	public static ArrayList<Boolean> unirErrores(ArrayList<Boolean> e1,
			ArrayList<Boolean> e2, ArrayList<Boolean> e3) {
		return unirErrores(unirErrores(e1, e2), e3);
	}

	public static ArrayList<Boolean> unirErrores(ArrayList<Boolean> err,
			boolean b, int pos) {
		ArrayList<Boolean> error = new ArrayList<Boolean>(err);
		error.set(pos, error.get(pos) | b);
		return error;
	}

	public static ArrayList<Boolean> copiaErrores(ArrayList<Boolean> e1) {
		return new ArrayList<Boolean>(e1);
	}
	
	public static Tipo unirTipos(Tipo t1, Tipo t2) {

		if (t1.getTipo().equals("errorTipo"))
			return t1;
		if (t2.getTipo().equals("errorTipo"))
			return t2;
		return t1;
	}

	public static Tipo unirTipos(Tipo t1, Tipo t2, Tipo t3) {

		if (t1.getTipo().equals("errorTipo"))
			return t1;
		if (t2.getTipo().equals("errorTipo"))
			return t2;
		if (t3.getTipo().equals("errorTipo"))
			return t3;
		return t1;
	}

	public static Tipo unirTipos(Tipo t1, Tipo t2, Tipo t3, Tipo t4) {
		if (t1.getTipo().equals("errorTipo"))
			return t1;
		if (t2.getTipo().equals("errorTipo"))
			return t2;
		if (t3.getTipo().equals("errorTipo"))
			return t3;
		if (t4.getTipo().equals("errorTipo"))
			return t4;
		return t1;
	}
	
	public static Tipo unirTipos(Tipo t1, Tipo t2, Tipo t3, Tipo t4,Tipo t5) {
		if (t1.getTipo().equals("errorTipo"))
			return t1;
		if (t2.getTipo().equals("errorTipo"))
			return t2;
		if (t3.getTipo().equals("errorTipo"))
			return t3;
		if (t4.getTipo().equals("errorTipo"))
			return t4;
		if (t4.getTipo().equals("errorTipo"))
			return t5;
		return t1;
	}

	public static ArrayList<String> dameCod(ArrayList<String> cod1,
			ArrayList<String> cod2, String str, ArrayList<Boolean> err,
			Tipo tipo) {
		ArrayList<String> cod = new ArrayList<String>();
		cod.addAll(cod1);
		cod.addAll(cod2);
		cod.add(str);
		return cod;
	}

	public static ArrayList<String> copiaCod(ArrayList<String> cod,
			ArrayList<Boolean> err, Tipo tipo) {
		if (!hayError(err) && !tipo.getTipo().equals("errorTipo")) {
			return new ArrayList<String>(cod);
		}
		return new ArrayList<String>();
	}

	public static ArrayList<String> copiaCod(ArrayList<String> cod) {
		return new ArrayList<String>(cod);
	}

	public static ArrayList<String> concatenaCod(ArrayList<String> cod1,
			ArrayList<String> cod2, String str, ArrayList<Boolean> err,
			Tipo tipo) {
		ArrayList<String> cod = new ArrayList<String>();
		if (!hayError(err) && !tipo.getTipo().equals("errorTipo")) {
			cod.addAll(cod1);
			cod.addAll(cod2);
			cod.add(str);
		}
		return cod;
	}

	public static ArrayList<String> concatenaCod(ArrayList<String> cod1,
			ArrayList<String> cod2, ArrayList<Boolean> err, Tipo tipo) {
		ArrayList<String> cod = new ArrayList<String>();
		if (!hayError(err) && !tipo.getTipo().equals("errorTipo")) {
			cod.addAll(cod1);
			cod.addAll(cod2);
		}
		return cod;
	}

	public static ArrayList<String> concatenaCod(ArrayList<String> cod1,
			String str, ArrayList<Boolean> err, Tipo tipo) {
		ArrayList<String> cod = new ArrayList<String>();
		if (!hayError(err) && !tipo.getTipo().equals("errorTipo")) {
			cod.addAll(cod1);
			cod.add(str);
		}
		return cod;
	}

	public static ArrayList<String> concatenaCod(ArrayList<String> cod1,
			ArrayList<Boolean> err, Tipo tipo) {
		ArrayList<String> cod = new ArrayList<String>();
		if (!hayError(err) && !tipo.getTipo().equals("errorTipo")) {
			cod.addAll(cod1);
		}
		return cod;
	}

	public static ArrayList<String> concatenaCod(ArrayList<String> cod1,
			ArrayList<String> cod2, ArrayList<String> cod3) {
		ArrayList<String> cod = new ArrayList<String>();
		cod.addAll(cod1);
		cod.addAll(cod2);
		cod.addAll(cod3);
		return cod;
	}

	public static ArrayList<String> creaCod(String str) {
		ArrayList<String> cod = new ArrayList<String>();
		cod.add(str);
		return cod;
	}

	public static ArrayList<String> creaCod() {
		return new ArrayList<String>();
	}

	public static int tamDe(Tipo tipo, String clase) {
		if (clase.equals("tipo"))
			return 0;
		else {
			return tipo.getTam();
		}
	}

	public static float valorDe(Tipo tipo, String valor) {
		try {
			if (tipo.getTipo().equals("boolean")) {
				if (valor.equals("true"))
					return 1;
				else
					return 0;
			}
			if (tipo.getTipo().equals("character")) {
				return valor.charAt(1);
			}
			if (tipo.getTipo().equals("natural"))
				return Integer.parseInt(valor);

			if (tipo.getTipo().equals("integer"))
				return Integer.parseInt(valor);

			if (tipo.getTipo().equals("float"))
				return Float.parseFloat(valor);

			return 0;
		} catch (Exception e) {
			return 0;
		}
	}

	public static Tipo tipoDe(Tipo tipo, String valor) {
		try {
			if (tipo.getTipo().equals("boolean")
					&& (valor.equals("true") || valor.equals("false")))
				return tipo;
			else if (tipo.getTipo().equals("natural")
					&& ((TipoNat) tipo).getValor() >= 0) {
				Integer.parseInt(valor);

				return tipo;
			} else if (tipo.getTipo().equals("integer")) {
				Integer.parseInt(valor);
				return tipo;
			} else if (tipo.getTipo().equals("float")) {
				Float.parseFloat(valor);
				return tipo;
			} else if (tipo.getTipo().equals("character")
					&& valor.length() == 3) {
				return tipo;
			} else
				return new TipoError();
		} catch (Exception e) {
			return new TipoError();
		}

	}

	public static Tipo tipoDe(String id, TablaSimbolos ts) {
		if (ts.existeId(id) && !ts.esConst(id))
			return new TipoIdent(id, ts.getTipo(id).getTam());
		else
			return new Tipo("errorTipo");
	}

	public static int numInstrucciones(ArrayList<String> cod) {
		return cod.size();
	}

	public static ArrayList<String> inicializarTipo(Tipo tipo, int dir,
			TablaSimbolos ts) {
		ArrayList<String> al = new ArrayList<String>();

		if (esTipoBasico(tipo)) {
			al.addAll(inicializarTipoBasico(tipo, dir));
		} else if (tipo.getTipo().equals("array")) {
			al.addAll(inicializarTipoArray((TipoArray) tipo, dir, ts));
		} else if (tipo.getTipo().equals("tupla")) {
			al.addAll(inicializarTipoTupla((TipoTupla) tipo, dir, ts));
		} else if (tipo.getTipo().equals("ref"))
			al.addAll(inicializarTipo(
					ts.getTipo(((TipoIdent) tipo).getId()), dir, ts));
		return al;
	}

	private static ArrayList<String> inicializarTipoBasico(Tipo tipo, int dir) {
		ArrayList<String> al = new ArrayList<String>();
		al.add("apila(0)");
		al.add("desapila_dir(" + dir + ")");
		return al;
	}

	private static ArrayList<String> inicializarTipoArray(TipoArray tipo,
			int dir, TablaSimbolos ts) {
		ArrayList<String> al = new ArrayList<String>();
		for (int i = 0; i < tipo.getNumElem(); i++) {
			al.addAll(inicializarTipo(tipo.getTipoBase(), dir, ts));
			dir += ((TipoArray) tipo).getTipoBase().getTam();
		}

		return al;
	}

	private static ArrayList<String> inicializarTipoTupla(TipoTupla tipo,
			int dir, TablaSimbolos ts) {
		ArrayList<String> al = new ArrayList<String>();
		ArrayList<ParamTupla> tupla = tipo.getCampos();
		Iterator<ParamTupla> it = tupla.iterator();

		while (it.hasNext()) {
			ParamTupla campo = it.next();
			al.addAll(inicializarTipo(campo.getTipo(), dir + campo.getDesp(),
					ts));
		}

		return al;
	}

	public static Tipo creaBoolean() {
		return new TipoBool();
	}

	public static Tipo creaCharacter() {
		return new TipoChar();
	}

	public static Tipo creaNatural() {
		return new TipoNat();
	}

	public static Tipo creaInteger() {
		return new TipoInt();
	}

	public static Tipo creaFloat() {
		return new TipoFloat();
	}

	public static Tipo creaArray(int tam, Tipo tipo) {
		if (tipo.getTipo().equals("errorTipo"))
			return new TipoError();
		return new TipoArray(tam, tipo);
	}

	public static boolean esTipoBasico(Tipo tipo) {
		return tipo.getTipo().equals("boolean")
				|| tipo.getTipo().equals("character")
				|| tipo.getTipo().equals("natural")
				|| tipo.getTipo().equals("integer")
				|| tipo.getTipo().equals("float");
	}

	public static Tipo creaTupla(ArrayList<ParamTupla> campos,
			ArrayList<Boolean> err, Tipo tipo) {
		if (!hayError(err) && !tipo.getTipo().equals("errorTipo"))
			return new TipoTupla(campos);
		else
			return new TipoError();
	}

	public static Tipo creaTuplaVacia() {
		return new TipoTupla(new ArrayList<ParamTupla>());
	}

	public static Hashtable<String, Tipo> consultaTipoResultante() {
		Hashtable<String, Tipo> tablaOperadores = new Hashtable<String, Tipo>();
		
		tablaOperadores.put("naturalnaturalmayor", new TipoBool());
		tablaOperadores.put("naturalintegermayor", new TipoBool());
		tablaOperadores.put("naturalfloatmayor", new TipoBool());
		tablaOperadores.put("integerintegermayor", new TipoBool());
		tablaOperadores.put("integerfloatmayor", new TipoBool());
		tablaOperadores.put("integernaturalmayor", new TipoBool());
		tablaOperadores.put("floatintegermayor", new TipoBool());
		tablaOperadores.put("floatfloatmayor", new TipoBool());
		tablaOperadores.put("floatnaturalmayor", new TipoBool());
		tablaOperadores.put("charactercharactermayor", new TipoBool());
		tablaOperadores.put("booleanbooleanmayor", new TipoBool());
		
		tablaOperadores.put("naturalintegermenorIgual", new TipoBool());
		tablaOperadores.put("naturalfloatmenorIgual", new TipoBool());
		tablaOperadores.put("naturalnaturalmenorIgual", new TipoBool());
		tablaOperadores.put("integernaturalmenorIgual", new TipoBool());
		tablaOperadores.put("integerintegermenorIgual", new TipoBool());
		tablaOperadores.put("integerfloatmenorIgual", new TipoBool());
		tablaOperadores.put("floatnaturalmenorIgual", new TipoBool());
		tablaOperadores.put("floatintegermenorIgual", new TipoBool());
		tablaOperadores.put("floatfloatmenorIgual", new TipoBool());
		tablaOperadores.put("charactercharactermenorIgual", new TipoBool());
		tablaOperadores.put("booleanbooleanmenorIgual", new TipoBool());
		
		tablaOperadores.put("naturalnaturalmenor", new TipoBool());
		tablaOperadores.put("naturalintegermenor", new TipoBool());
		tablaOperadores.put("naturalfloatmenor", new TipoBool());
		tablaOperadores.put("integernaturalmenor", new TipoBool());
		tablaOperadores.put("integerintegermenor", new TipoBool());
		tablaOperadores.put("integerfloatmenor", new TipoBool());
		tablaOperadores.put("floatintegermenor", new TipoBool());
		tablaOperadores.put("floatfloatmenor", new TipoBool());
		tablaOperadores.put("floatnaturalmenor", new TipoBool());
		tablaOperadores.put("charactercharactermenor", new TipoBool());
		tablaOperadores.put("booleanbooleanmenor", new TipoBool());

		tablaOperadores.put("naturalnaturalmayorIgual", new TipoBool());
		tablaOperadores.put("naturalintegermayorIgual", new TipoBool());
		tablaOperadores.put("naturalfloatmayorIgual", new TipoBool());
		tablaOperadores.put("integernaturalmayorIgual", new TipoBool());
		tablaOperadores.put("integerintegermayorIgual", new TipoBool());
		tablaOperadores.put("integerfloatmayorIgual", new TipoBool());
		tablaOperadores.put("floatnaturalmayorIgual", new TipoBool());
		tablaOperadores.put("floatintegermayorIgual", new TipoBool());
		tablaOperadores.put("floatfloatmayorIgual", new TipoBool());
		tablaOperadores.put("charactercharactermayorIgual", new TipoBool());
		tablaOperadores.put("booleanbooleanmayorIgual", new TipoBool());

		tablaOperadores.put("naturalnaturaldistinto", new TipoBool());
		tablaOperadores.put("naturalintegerdistinto", new TipoBool());
		tablaOperadores.put("naturalfloatdistinto", new TipoBool());
		tablaOperadores.put("integernaturaldistinto", new TipoBool());
		tablaOperadores.put("integerintegerdistinto", new TipoBool());
		tablaOperadores.put("integerfloatdistinto", new TipoBool());
		tablaOperadores.put("floatnaturaldistinto", new TipoBool());
		tablaOperadores.put("floatintegerdistinto", new TipoBool());
		tablaOperadores.put("floatfloatdistinto", new TipoBool());
		tablaOperadores.put("charactercharacterdistinto", new TipoBool());
		tablaOperadores.put("booleanbooleandistinto", new TipoBool());
		
		tablaOperadores.put("naturalnaturaligual", new TipoBool());
		tablaOperadores.put("naturalintegerigual", new TipoBool());
		tablaOperadores.put("naturalfloatigual", new TipoBool());
		tablaOperadores.put("integernaturaligual", new TipoBool());
		tablaOperadores.put("integerintegerigual", new TipoBool());
		tablaOperadores.put("integerfloatigual", new TipoBool());
		tablaOperadores.put("floatnaturaligual", new TipoBool());
		tablaOperadores.put("floatintegerigual", new TipoBool());
		tablaOperadores.put("floatfloatigual", new TipoBool());
		tablaOperadores.put("charactercharacterigual", new TipoBool());
		tablaOperadores.put("booleanbooleanigual", new TipoBool());

		tablaOperadores.put("naturalnaturalsuma", new TipoNat());
		tablaOperadores.put("naturalintegersuma", new TipoNat());
		tablaOperadores.put("naturalfloatsuma", new TipoFloat());
		tablaOperadores.put("integernaturalsuma", new TipoNat());
		tablaOperadores.put("integerintegersuma", new TipoNat());
		tablaOperadores.put("integerfloatsuma", new TipoFloat());
		tablaOperadores.put("floatnaturalsuma", new TipoFloat());
		tablaOperadores.put("floatintegersuma", new TipoFloat());
		tablaOperadores.put("floatfloatsuma", new TipoFloat());

		tablaOperadores.put("naturalnaturalresta", new TipoNat());
		tablaOperadores.put("naturalintegerresta", new TipoNat());
		tablaOperadores.put("naturalfloatresta", new TipoFloat());
		tablaOperadores.put("integernaturalresta", new TipoNat());
		tablaOperadores.put("integerintegerresta", new TipoNat());
		tablaOperadores.put("integerfloatresta", new TipoFloat());
		tablaOperadores.put("floatnaturalresta", new TipoFloat());
		tablaOperadores.put("floatintegerresta", new TipoFloat());
		tablaOperadores.put("floatfloatresta", new TipoFloat());

		tablaOperadores.put("naturalnaturalmultiplica", new TipoNat());
		tablaOperadores.put("naturalintegermultiplica", new TipoNat());
		tablaOperadores.put("naturalfloatmultiplica", new TipoFloat());
		tablaOperadores.put("integernaturalmultiplica", new TipoNat());
		tablaOperadores.put("integerintegermultiplica", new TipoNat());
		tablaOperadores.put("integerfloatmultiplica", new TipoFloat());
		tablaOperadores.put("floatnaturalmultiplica", new TipoFloat());
		tablaOperadores.put("floatintegermultiplica", new TipoFloat());
		tablaOperadores.put("floatfloatmultiplica", new TipoFloat());

		tablaOperadores.put("naturalnaturaldivide", new TipoNat());
		tablaOperadores.put("naturalintegerdivide", new TipoNat());
		tablaOperadores.put("naturalfloatdivide", new TipoFloat());
		tablaOperadores.put("integernaturaldivide", new TipoNat());
		tablaOperadores.put("integerintegerdivide", new TipoNat());
		tablaOperadores.put("integerfloatdivide", new TipoFloat());
		tablaOperadores.put("floatnaturaldivide", new TipoFloat());
		tablaOperadores.put("floatintegerdivide", new TipoFloat());
		tablaOperadores.put("floatfloatdivide", new TipoFloat());

		tablaOperadores.put("booleanbooleanand", new TipoBool());
		tablaOperadores.put("booleanbooleanor", new TipoBool());

		tablaOperadores.put("naturalnaturaldesplazarDer", new TipoNat());
		tablaOperadores.put("naturalnaturaldesplazarIzq", new TipoNat());

		tablaOperadores.put("naturalnaturalmodulo", new TipoNat());
		tablaOperadores.put("integernaturalmodulo", new TipoNat());

		tablaOperadores.put("naturalnegativo", new TipoNat());
		tablaOperadores.put("integernegativo", new TipoInt());
		tablaOperadores.put("floatnegativo", new TipoFloat());
		tablaOperadores.put("naturalnegativo", new TipoNat());

		tablaOperadores.put("booleannot", new TipoBool());
		tablaOperadores.put("natural(int)", new TipoNat());
		tablaOperadores.put("integer(int)", new TipoNat());
		tablaOperadores.put("float(int)", new TipoNat());
		tablaOperadores.put("character(int)", new TipoNat());

		tablaOperadores.put("natural(nat)", new TipoNat());
		tablaOperadores.put("character(nat)", new TipoNat());

		tablaOperadores.put("natural(char)", new TipoChar());
		tablaOperadores.put("character(char)", new TipoChar());
		
		tablaOperadores.put("natural(float)", new TipoFloat());
		tablaOperadores.put("integer(float)", new TipoFloat());
		tablaOperadores.put("boolean(float)", new TipoFloat());
		tablaOperadores.put("float(float)", new TipoFloat());
		tablaOperadores.put("character(float)", new TipoFloat());

		return tablaOperadores;
	}

	public static Tipo consultarTipoResultante(String s) {
		Hashtable<String, Tipo> tablaOperadores = consultaTipoResultante();
		Tipo tipo = tablaOperadores.get(s);
		if (tipo != null)
			return tipo;
		else
			return new TipoError();
	}

	public static boolean tiposCompatibles(Tipo tipo1, Tipo tipo2,TablaSimbolos ts) {
		tipo1 = tipoRec(tipo1, ts);
		tipo2 = tipoRec(tipo2, ts);
		if (tipo1.getTipo().equals("character")
				&& tipo2.getTipo().equals("character"))
			return true;
		if (tipo1.getTipo().equals("boolean")
				&& tipo2.getTipo().equals("boolean"))
			return true;
		if (tipo1.getTipo().equals("natural")
				&& tipo2.getTipo().equals("natural"))
			return true;
		if (tipo1.getTipo().equals("integer")
				&& tipo2.getTipo().equals("integer"))
			return true;
		if (tipo1.getTipo().equals("integer")
				&& tipo2.getTipo().equals("natural"))
			return true;
		if (tipo1.getTipo().equals("float") && tipo2.getTipo().equals("float"))
			return true;
		if (tipo1.getTipo().equals("float")
				&& tipo2.getTipo().equals("integer"))
			return true;
		if (tipo1.getTipo().equals("float")
				&& tipo2.getTipo().equals("natural"))
			return true;
		if (tipo1.getTipo().equals("array") && tipo2.getTipo().equals("array"))
			return ((TipoArray) tipo1).getNumElem() == ((TipoArray) tipo2)
					.getNumElem()
					&& tiposCompatibles(((TipoArray) tipo1).getTipoBase(),
							((TipoArray) tipo2).getTipoBase(), ts);
		if (tipo1.getTipo().equals("tupla") && tipo2.getTipo().equals("tupla")) {
			if (((TipoTupla) tipo1).getCampos().size() != ((TipoTupla) tipo2)
					.getCampos().size())
				return false;
			for (int i = 0; i < ((TipoTupla) tipo1).getCampos().size(); i++)
				if (!tiposCompatibles(((TipoTupla) tipo1).getTipoTuplaPos(i),
						((TipoTupla) tipo2).getTipoTuplaPos(i), ts))
					return false;
			return true;
		}
		return false;
	}

	public static Tipo tipoRec(Tipo tipo, TablaSimbolos tabla) {

		if (tipo.getTipo().equals("ref")) {
			String id = ((TipoIdent) tipo).getId();
			Tipo tipoRec = tabla.getTipo(id);
			if (!tipoRec.getTipo().equals("errorTipo"))
				return tipoRec(tipoRec, tabla);
		}
		return tipo;
	}

	public static TablaSimbolos borrarTSL(TablaSimbolos ts) {
		TablaSimbolos tsNueva = new TablaSimbolos(ts);
		tsNueva.eliminaTSLocal();
		return tsNueva;
	}

	public static TablaSimbolos creaTSL(TablaSimbolos ts) {
		TablaSimbolos tsNueva = new TablaSimbolos(ts);
		tsNueva.creaTSLocal();
		return tsNueva;
	}

	public static Object creaProc(ArrayList<ParamProc> lista, String id,
			Tipo tipo1, Tipo tipo2) {
		if (!tipo1.getTipo().equals("errorTipo")
				&& !tipo2.getTipo().equals("errorTipo"))
			return new TipoProc(lista);
		else
			return new TipoError();
	}

	public static ArrayList<String> crearPrologo(int sizeVar) {

		ArrayList<String> prologo = new ArrayList<String>();
		prologo.add("apila_dir(0)");
		prologo.add("apila(2)");
		prologo.add("suma");
		prologo.add("apila_dir(1)");
		prologo.add("desapila_ind");
		prologo.add("apila_dir(0)");
		prologo.add("apila(3)");
		prologo.add("suma");
		prologo.add("desapila_dir(1)");
		prologo.add("apila_dir(0)");
		prologo.add("apila(" + (sizeVar + 2) + ")");
		prologo.add("suma");
		prologo.add("desapila_dir(0)");

		return prologo;
	}

	public static ArrayList<String> crearEpilogo(int tamVariables) {

		ArrayList<String> epilogo = new ArrayList<String>();
		epilogo.add("apila_dir(0)");
		epilogo.add("apila(" + (tamVariables + 2) + ")");
		epilogo.add("resta");
		epilogo.add("desapila_dir(0)");
		epilogo.add("apila_dir(0)");
		epilogo.add("apila(2)");
		epilogo.add("suma");
		epilogo.add("apila_ind");
		epilogo.add("desapila_dir(1)");
		epilogo.add("apila_dir(0)");
		epilogo.add("apila(1)");
		epilogo.add("suma");
		epilogo.add("apila_ind");
		return epilogo;
	}

	public static ArrayList<String> cod_dirRetorno(int dir) {

		ArrayList<String> ret = new ArrayList<String>();
		ret.add("apila_dir(0)");
		ret.add("apila(1)");
		ret.add("suma");
		ret.add("apila(" + dir + ")");
		ret.add("desapila_ind");
		return ret;
	}
}
